#pragma once
#include "Socket.hpp"
#include "Common.hpp"
#include "Log.hpp"

using namespace SocketModule;
using namespace LogModule;

class Request
{
public:
    Request()
    {}
    Request(int x, int y, char oper):_x(x), _y(y), _oper(oper)
    {

    }
    std::string Serialize()
    {
        Json::Value root;
        root["x"] = _x;
        root["y"] = _y;
        root["oper"] = _oper;

        Json::FastWriter writer;
        std::string s = writer.write(root);
        return s;
    }

    bool Deserialize(std::string &in)
    {
        Json::Value root;
        Json::Reader reader;
        bool ok = reader.parse(in, root);
        if(ok)
        {
            _x = root["x"].asInt();
            _y = root["y"].asInt();
            _oper = root["oper"].asInt();
        }
        return ok;
    }

    int Y() {return _y;}
    int X() {return _x;}
    char Oper() {return _oper;}
    ~Request()
    {}
private:
    int _x;
    int _y;
    char _oper;
};

class Response
{
public:
    Response()
    {}
    Response(int result, int code):_result(result), _code(code)
    {}
    std::string Serialize()
    {
        Json::Value root;
        root["result"] = _result;
        root["code"] = _code;

        Json::FastWriter writer;
        return writer.write(root);
    }

    bool Deserialize(std::string &in)
    {
        Json::Value root;
        Json::Reader reader;
        bool ok = reader.parse(in, root);
        if(ok)
        {
            _result = root["result"].asInt();
            _code = root["code"].asInt();
        }
        return ok;
    }  
    ~Response()
    {}

    void SetResult(int res)
    {
        _result = res;
    }
    
    void SetCode(int code)
    {
        _code = code;
    }

    void ShowResult()
    {
        std::cout << "运算结果是：" << _result << "[" << _code << "]" << std::endl;
    }
private:
    int _result;
    int _code;
};


const std::string sep = "\r\n";
using func_t = std::function<Response (Request &req)>;
class Protocol
{
public:
    Protocol()
    {

    }
    Protocol(func_t func): _func(func)
    {}

    std::string Encode(const std::string &jsonstr)
    {
        //50\r\n{"x": 10, "y": 20,  "oper": "+"}\r\n
        std::string len = std::to_string(jsonstr.size());
        return len + sep + jsonstr + sep;
    }
    //1.判断报文完整性
    //2.如果包含至少一个完整请求，提取他，并移除，方便处理下一个
    bool Decode(std::string &buffer, std::string *package)
    {
        ssize_t pos = buffer.find(sep);
        if(pos == std::string::npos)//让调用方继续从内核读取数据    
            return false;
        std::string package_len_str = buffer.substr(0, pos);
        int package_len_int = std::stoi(package_len_str);
        //buffer一定有长度，但不一定有完整的报文
        int target_len = package_len_str.size() + package_len_int + 2 * sep.size();
        if(buffer.size() < target_len)
            return false;
        *package = buffer.substr(pos + sep.size(), package_len_int);
        buffer.erase(0, target_len);
        return true;
    }

    void GetRequest(std::shared_ptr<Socket> &sock, InetAddr &client)
    {
        std::string buffer_queue;
        while(true)
        {
            int n = sock->Recv(&buffer_queue);
            if( n > 0)
            {
                std::cout << "------------request_buffer-------------" << std::endl;
                std::cout << buffer_queue << std::endl;
                std::cout << "------------------------------------" << std::endl;
                std::string json_package;
                //1.解析报文，提取完整的json请求，如果不完整，就让服务器继续读取
                while(Decode(buffer_queue, &json_package))
                {
                    //有了完整报文
                    //2.请求json串，反序列化
                    // std::cout << "------------request_json-------------" << std::endl;
                    // std::cout << json_package << std::endl;
                    // std::cout << "------------------------------------" << std::endl;

                    // std::cout << "------------request_buffer-------------" << std::endl;
                    // std::cout << buffer_queue << std::endl;
                    // std::cout << "------------------------------------" << std::endl;
                    LOG(LogLevel::DEBUG) << client.StringAddr() << "请求：" << json_package;
                    Request req;
                    bool ok = req.Deserialize(json_package);
                    if(!ok)
                        continue;
                    //业务
                    Response resp = _func(req);
                    //序列化
                    std::string json_str = resp.Serialize();

                    //添加自定义长度
                    std::string send_str = Encode(json_str);

                    //直接发送
                    sock->Send(send_str);
                }
            }
            else if(n == 0)
            {
                LOG(LogLevel::INFO) << "client" << client.StringAddr() << "Quit!";
                break;
            }
            else
            {
                LOG(LogLevel::WARNING) << "client:" << client.StringAddr() << ", recv error";
                break;
            }
        }
    }

    bool GetReponse(std::shared_ptr<Socket> &client, std::string &resp_buff, Response *resp)
    {
        //面向字节流
        while(true)
        {
            int n = client->Recv(&resp_buff);
            if(n > 0)
            {
                // std::cout << "------------resp_buffer-------------" << std::endl;
                // std::cout << resp_buff << std::endl;
                // std::cout << "------------------------------------" << std::endl;
                //成功
                std::string json_package;
                    //1.解析报文，提取完整的json请求，如果不完整，就让服务器继续读取
                // bool ret = Decode(resp_buff, &json_package);
                // if(!ret)
                //     continue;

                while(Decode(resp_buff, &json_package))
                {
                    // std::cout << "-----------response json-------------" << std::endl;
                    // std::cout << json_package << std::endl;
                    // std::cout << "-------------------------------------" << std::endl;

                    // std::cout << "-----------resp_buffer---------------" << std::endl;
                    // std::cout << resp_buff << std::endl;
                    // std::cout << "-------------------------------------" << std::endl;
                    //拿到了一个完整的应答json报文
                    //反序列化
                    resp->Deserialize(json_package);
                    resp->ShowResult();
                }
                return true;
            }
            else if(n == 0)
            {
                std::cout << "server quit" << std::endl;
                return false;
            }
            else
            {
                std::cout << "recv error" << std::endl;
                return false;
            }
        }
    }

    std::string BuildRequestString(int x, int y, char oper)
    {
        //1.构建一个完整的请求
        Request req(x, y, oper);

        //2.序列化
        std::string json_req = req.Serialize();

        // std::cout << "----------json_req string-----------" << std::endl;
        // std::cout << json_req << std::endl;
        // std::cout << "------------------------------------" << std::endl;

        //3.添加长度报头
        return Encode(json_req);

    }
    ~Protocol(){};
private:
    Request _req;
    Response _resp;
    func_t _func;
};